﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Xml.Linq;

using BLL;
using System.Text.RegularExpressions;
using System.IO;
using NUnrar.Archive;

namespace CTRL
{
    public class CtrlDemos
    {
        private static CtrlDemos instance = null;
        private static readonly object padlock = new object();
        private static readonly string demoListURL = String.Format("{0}\\{1}", System.IO.Directory.GetCurrentDirectory(),"demos.xml");
        private static readonly string lastReleaseURL = String.Format("{0}\\{1}", System.IO.Directory.GetCurrentDirectory(),"last_release.xml");
        private List<Record> demoList;
        private List<Record> lastReleaseList;
        private CtrlMaps ctrlMaps;
        private CtrlJumper ctrlJumper;

        public CtrlDemos()
        {
            demoList = new List<Record>();
            lastReleaseList = new List<Record>();

            ctrlMaps = CtrlMaps.Instance;
            ctrlJumper = CtrlJumper.Instance;

            LoadDemoFile();
            LoadLastReleaseFile();
        }

        public List<Record> GetDemoList()
        {
            return demoList;
        }

        public List<Record> GetLastReleastList()
        {
            return lastReleaseList;
        }

        public void DownloadDemo(string file)
        {
            string pathToFile = Path.Combine(UTIL.KZSettings.DemoFolder, file);

            try
            {

                bool isExists = Directory.Exists(UTIL.KZSettings.DemoFolder);

                if (!isExists)
                    Directory.CreateDirectory(UTIL.KZSettings.DemoFolder);
            }
            catch(Exception e)
            {
                Console.WriteLine(e.Message);
            }

            using (WebClient myWebClient = new WebClient())
            {
                try
                {
                    if (!File.Exists(pathToFile))
                    {
                        myWebClient.DownloadFile(System.IO.Path.Combine(UTIL.KZSettings.DemoURL, file), pathToFile);

                        RarArchive archive = RarArchive.Open(pathToFile);
                        foreach (RarArchiveEntry entry in archive.Entries)
                        {
                            // Normally we would use entry.FilePath() 
                            // but some of the archives have wrong headers
                            // and cause the Exception throw of IllegalArguments
                            // therefore this is a sloppy, but a secure way to do this
                           
                            string path = pathToFile.Remove(pathToFile.Length - 4) + ".dem";

                            entry.WriteToFile(path);
                        }
                    }
                }
                catch (Exception)
                {
                   //todo: do something!
                }
            }
        }

        public List<Record> LoadDemoFile()
        {
            demoList.Clear();

            var maps = ctrlMaps.GetMapList();
            var jumpers = ctrlJumper.GetJumpers();

            var xml = XDocument.Load(demoListURL).Descendants("map").ToList();

            foreach (var x in xml)
            {
                var map = maps.FirstOrDefault(d => d.DemoID.Equals(Int32.Parse(x.Element("id").Value)));

                if (map != null)
                {
                    demoList.Add(
                        new Record
                        {
                            Map = map,
                            Time = Double.Parse(x.Element("record").Value.ToString()),
                            Jumper = jumpers.FirstOrDefault(j => j.ID == Int32.Parse(x.Element("jumper").Value)),
                            File = x.Element("file").Value.ToString(),
                            Beaten = Int32.Parse(x.Element("beaten").Value),
                            Date = UTIL.DateTimeFromUNIXTimestamp.UnixTimeStampToDateTime(Double.Parse(x.Element("date").Value))
                        }
                    );
                }
            }

            return demoList;
        }

        public List<Record> LoadLastReleaseFile()
        {
            lastReleaseList.Clear();

            var demos = this.GetDemoList();
            var jumpers = ctrlJumper.GetJumpers();

            var xml = XDocument.Load(lastReleaseURL).Descendants("demo").ToList();

            foreach (var x in xml)
            {
                var record = demos.SingleOrDefault(d => d.Map.Name.Equals(x.Element("map").Value));

                if (record != null)
                {
                    lastReleaseList.Add(record);
                }
            }

            return lastReleaseList;
        }

        public static CtrlDemos Instance
        {
            get
            {
                lock (padlock)
                {
                    if (instance == null)
                    {
                        instance = new CtrlDemos();
                    }

                    return instance;
                }
            }
        }
    }
}